
//---------------------------------------------------------------------------
// Copyright (c) 2011 Texas Instruments, Inc.
// This is an unpublished work created in the year stated above.
// Texas Instruments owns all rights in and to this work and
// intends to maintain and protect it as an unpublished copyright.
// In the event of either inadvertent or deliberate publication,
// the above stated date shall be treated as the year of first
// publication. In the evxfent of such publication, Texas Instruments
// intends to enforce its rights in the work under the copyright
// laws as a published work.
//----------------------------------------------------------------------------
// Filename                : message_handler.c
//
// Functional Description  : SMS Common Protocol message handler
//----------------------------------------------------------------------------

#include "DRV922XX.h"
#include "monterey_uart.h"
#include "message_protocol.h"

unsigned char response_buffer[5];
unsigned char checksum_accumulator = 0;

// function prototypes

int checksum_valid();
void generate_checksum();

/*
 * \fn void msg_protocol_handler()
 * \brief Called by UART state machine when UART message successfully received
 * 
 * Each protocol message has the following contents:
 * 
 * HOST >> Micro-controller
 * 
 *   Write Message (write to memory on controller)
 *   ---------------------------------------------
 *   Byte 0:		Command code 		[maps to memory to write to]
 *   Byte 1: 		Operation        	[0: Write]
 *   Byte 2:		Data Hi to write 
 *   Byte 3: 		Data Lo to write
 *   Byte 4: 		Checksum
 * 
 *   Read Message (read from memory on controller)
 *   ---------------------------------------------
 *   Byte 0:		Command code		[maps to memory to read from]
 *   Byte 1:		Operation			[1: Read]
 *   Byte 2:		n/a
 *   Byte 3:		n/a
 *   Byte 4: 		Checksum
 *  
 * Micro-controller >> HOST (responses):
 * 
 *	 Response message (write to memory)
 *   ----------------------------------
 *   Byte 0:		Command code (response)
 *   Byte 1: 		Status
 *   Byte 2:		n/a
 *   Byte 3:		n/a
 *   Byte 4: 		Checksum
 * 
 *   Response message (read from memory)
 *   -----------------------------------
 *   Byte 0: 		Command code (response)
 *   Byte 1:		Status
 *   Byte 2: 		Data (MSB)
 *   Byte 3:		Data (LSB)
 *   Byte 4: 		Checksum
 * 
 * This function is called when a completed message has been received from the host. This function
 * will process the message and send an appropriate response back to the host, indicating if it got
 * the message, and if the message is valid.
 * 
 * INPUTS:
 * 
 *   - uart_rx_buffer[]:		Contains received message before this function is called
 * 
 * OUTPUTS:
 * 
 *   - response_buffer[]: 		Contains message to transmit back to host after processing complete
 */
void msg_protocol_handler()
{
	unsigned int *pData;
	unsigned char cmd = uart_rx_buffer[0];
	unsigned char read = uart_rx_buffer[1];
	unsigned int data;
	
	response_buffer[0] = cmd;
	
	if (!checksum_valid())
	{
		response_buffer[1] = MSG_STATUS_INVALID_CSUM;
	}
	else
	{
		response_buffer[1] = MSG_STATUS_SUCCESS;
	
		if (read)						// Read commands
		{
			switch (cmd)
			{
				case CmdDeviceType:
					pData = &MsgDeviceId;
					break;
				case CmdFwVersion:
					pData = &MsgFwVersion;
					break;
				case CmdAdminState:
					pData = &MsgAdminState;
					break;
				case CmdSetAddr:
					pData = &MsgAddrPtr;
					break;
				case CmdPeek:
					pData = (unsigned int*)MsgAddrPtr;
					break;
				case CmdAfeRead:
					data = drv922xxSpiRead(uart_rx_buffer[3]);
					pData = &data;
					break;
				default:
					pData = (unsigned int *)message_handler_application_read();		// Callback to application to supply application-dependent data to read
			}
			
			if (pData != (unsigned int*)0xFFFF)
			{
				response_buffer[2] = (*pData >> 8);
				response_buffer[3] = (*pData & 0xFF);
			}
			else
				response_buffer[1] = MSG_STATUS_INVALID_CMD;		// Invalid read command
				 
		}
		else							// Write commands
		{
			pData = 0;				// Set to non-zero for error checking below
			
			switch (cmd)
			{
				case CmdAdminState:
					MsgAdminState = (uart_rx_buffer[2] << 8) | uart_rx_buffer[3];
					break;
				case CmdSetAddr:
					MsgAddrPtr = (uart_rx_buffer[2] << 8) | uart_rx_buffer[3];
					break;
				case CmdPoke:
					*((unsigned int*)MsgAddrPtr) = (uart_rx_buffer[2] << 8) | uart_rx_buffer[3];
					break;
				case CmdAfeWrite:
					drv922xxSpiWrite(uart_rx_buffer[2], uart_rx_buffer[3]);
					break;
				case CmdSaveParams:
					msg_protocol_save_parameters();
					break;
				case CmdRestoreDefaults:
					msg_protocol_reset_defaults();
					break;
				default:
					data = (uart_rx_buffer[2] << 8) | uart_rx_buffer[3];
					pData = (unsigned int *)message_handler_application_write(data);
					break;
			}
			
			if (pData == (unsigned int*)0xFFFF)
				response_buffer[1] = MSG_STATUS_INVALID_CMD;		// Invalid write command
		}
					
		// Send response to host
		
		generate_checksum();
		uart_transmit(&response_buffer[0], 5);
	}
}

/*
 * \fn int checksum_valid()
 * \brief Called to see if the incoming received buffer has a valid checksum
 * 
 * Returns 0 if not valid, 1 if valid.
 */
 
int checksum_valid()
{
	unsigned char sum = 0;
	unsigned char *data = &uart_rx_buffer[0];
	
	sum += *data++;		// Byte 0
	sum += *data++;		// Byte 1
	sum += *data++;		// Byte 2
	sum += *data++;		// Byte 3
	
	if (sum != *data)	// Byte 4 - checksum
		return 0;
		
	return 1;
}

/* \fn void generate_checksum()
 * \brief Generates an 8b checksum for the response_buffer[] and puts it at the end of the buffer
 */
 
void generate_checksum()
{
	unsigned char sum = 0;
	unsigned char *data = &response_buffer[0];
	
	sum += *data++;		// Byte 0
	sum += *data++;		// Byte 1
	sum += *data++;		// Byte 2
	sum += *data++;		// Byte 3
	
	response_buffer[4] = sum;
}


